<?php

//Autor: Carlos García Trujillo.

class Generic_Dataset_Model extends CI_Model
{

    protected $table;

    protected $primary_key = 'id';

    protected $before_create = array();

    protected $after_create = array();

    public function __construct()
    {
        parent :: __construct();
        $this->_fetch_table();
    }

    public function get($primary_value)
    {
        $this->db->where($this->primary_key, $primary_value);
        return $this->db->get($this->table)->row();
    }

    public function get_by()
    {
        $where = &func_get_args();
        $this->_set_where($where);
        return $this->db->get($this->table)->row();
    }

    public function get_many_by()
    {
        $where = &func_get_args();
        $this->_set_where($where);
        return $this->get_all();
    }

    public function get_all()
    {
        return $this->db->get($this->table)->result();
    }

    public function count_by()
    {
        $where = &func_get_args();
        $this->_set_where($where);
        return $this->db->count_all_results($this->table);
    }

    public function count_all()
    {
        return $this->db->count_all($this->table);
    }

    public function insert($data)
    {
        $data = $this->_run_before_create($data);
        $this->db->insert($this->table, $data);
        $this->_run_after_create($data, $this->db->insert_id());
        return $this->db->insert_id();
    }

    public function insert_many($data)
    {
        $ids = array();
        foreach ($data as $row)
        {
            $data = $this->_run_before_create($row);
            $this->db->insert($this->table, $row);
            $this->_run_after_create($row, $this->db->insert_id());
            $ids[] = $this->db->insert_id();
        }
        return $ids;
    }

    public function update($primary_value, $array)
    {
        $this->db->where($this->primary_key, $primary_value);
        $this->db->set($array);
        return $this->db->update($this->table);
    }

    public function update_by($key, $val, $array)
    {
        $this->db->where($key, $val)->set($array);
        return $this->db->update($this->table);
    }

    public function update_many($primary_values, $array)
    {
        $this->db->where_in($this->primary_key, $primary_values);
        $this->db->set($array);
        return $this->db->update($this->table);
    }

    public function update_many_by($where, $data)
    {
        $this->db->where($where);
        $this->db->set($data);
        return $this->db->update($this->table);
    }

    public function delete($id)
    {
        $this->db->where($this->primary_key, $id);
        return $this->db->delete($this->table);
    }

    public function delete_by($key, $val)
    {
        $this->db->where($key, $val);
        return $this->db->delete($this->table);
    }

    public function delete_many($primary_values)
    {
        $this->db->where_in($this->primary_key, $primary_values);
        return $this->db->delete($this->table);
    }

    public function delete_many_by($where)
    {
        $this->db->where($where);
        return $this->db->delete($this->table);
    }

    public function limit($limit, $offset = 0)
    {
        $this->db->limit($limit, $offset);
    }

    private function _run_before_create($data)
    {
        foreach ($this->before_create as $method)
        {
            $data = call_user_func_array(array($this, $method), array($data));
        }
        return $data;
    }

    private function _run_after_create($data, $id)
    {
        foreach ($this->after_create as $method)
        {
            call_user_func_array(array($this, $method), array($data, $id));
        }
    }

    private function _fetch_table()
    {
        if ($this->table == NULL)
        {
            $class = preg_replace('/(_m|_model)?$/', '', get_class($this));
            $this->load->helper('inflector');
            $this->table = plural(strtolower($class));
        }
    }

    private function _set_where($params)
    {
        if (count($params) == 1)
        {
            $this->db->where($params[0]);
        } else
        {
            $this->db->where($params[0], $params[1]);
        }
    }
}
